package schedule

import (
	"container/heap"
	"cow_golang/shared_mod/logger"
	"cow_golang/shared_mod/schedule/iface"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"
)

// 类型
type exprType int

const (
	exprInvalid exprType = iota
	exprOnce
	exprInterval
	exprCron
)

// 队伍队列的任务项
type taskItem struct {
	execute  func()          // 用户回调
	next     time.Time       // 下次触发时间
	interval time.Duration   // 仅间隔任务使用
	schedule iface.ISchedule // Cron模式解析器
	exprType exprType        // 表达式类型
}

// 任务优先队列
type taskQueue []*taskItem

func (q taskQueue) Len() int           { return len(q) }
func (q taskQueue) Less(i, j int) bool { return q[i].next.Before(q[j].next) }
func (q taskQueue) Swap(i, j int)      { q[i], q[j] = q[j], q[i] }

func (q *taskQueue) Push(x interface{}) {
	*q = append(*q, x.(*taskItem))
}

func (q *taskQueue) Pop() interface{} {
	old := *q
	n := len(old)
	item := old[n-1]
	*q = old[0 : n-1]
	return item
}

// 轻量级调度器
// 1 支持crontab任务
// 2 支持一次性任务
// 3 周期间隔执行任务
type Schedule struct {
	//任务队列
	queue   *taskQueue
	addChan chan *taskItem
	mu      sync.Mutex
	stop    chan struct{}
	wakeup  chan struct{}
}

// 创建调度器实例
func NewSchedule() *Schedule {
	return &Schedule{
		queue:   &taskQueue{},
		addChan: make(chan *taskItem),
		stop:    make(chan struct{}),
		wakeup:  make(chan struct{}, 1),
	}
}

// 核心调度循环
func (s *Schedule) Start() {
	// 初始化堆，主要是排序
	heap.Init(s.queue)
	// 指定到期的任务
	go func() {
		for {
			s.mu.Lock()
			if s.queue.Len() == 0 {
				s.mu.Unlock()
				select {
				case item := <-s.addChan:
					heap.Push(s.queue, item)
				case <-s.stop:
					return
				}
				continue
			}

			now := time.Now()
			item := (*s.queue)[0]
			if item.next.After(now) {
				wait := item.next.Sub(now)
				s.mu.Unlock()
				timer := time.NewTimer(wait)
				select {
				case <-timer.C:
					s.mu.Lock()
					item = heap.Pop(s.queue).(*taskItem)
					s.mu.Unlock()
					s.executeAndReschedule(item)
				case newItem := <-s.addChan:
					s.mu.Lock()
					heap.Push(s.queue, newItem)
					s.mu.Unlock()
					timer.Stop()
				case <-s.stop:
					timer.Stop()
					return
				}
			} else {
				item := heap.Pop(s.queue).(*taskItem)
				s.mu.Unlock()
				s.executeAndReschedule(item)
			}
		}
	}()
}

// 停止调度器
func (s *Schedule) Stop() {
	close(s.stop)
}

// 用户接口：添加定时任务
func (s *Schedule) AddTask(expr string, callback func()) error {
	item, err := parseScheduleExpr(expr)
	if err != nil {
		return err
	}
	item.execute = callback
	s.addChan <- item
	return nil
}

// 任务执行与重新调度（带panic保护）
func (s *Schedule) executeAndReschedule(item *taskItem) {
	// 使用闭包包装执行逻辑
	go func() {
		defer func() {
			if r := recover(); r != nil {
				// 这里可以添加错误处理逻辑，例如：
				logger.GetInstance().Warnf("task panic recovered: %v\n", r)
			}
		}()
		item.execute() // 实际执行用户回调
	}()

	// 重新调度逻辑（保持原有逻辑）
	switch item.exprType {
	case exprOnce:
		return
	case exprInterval:
		item.next = time.Now().Add(item.interval)
		s.scheduleTask(item)
	case exprCron:
		item.next = item.schedule.Next(time.Now())
		s.scheduleTask(item)
	default:
		logger.GetInstance().Warn("unhandled default case")
	}
}

// 添加任务到队列
func (s *Schedule) scheduleTask(item *taskItem) {
	s.mu.Lock()
	heap.Push(s.queue, item)
	s.mu.Unlock()
	select {
	case s.wakeup <- struct{}{}:
	default:
	}
}

// 表达式解析器
func parseScheduleExpr(expr string) (*taskItem, error) {
	switch {
	case strings.HasPrefix(expr, "@once "):
		return parseOnceExpr(expr)
	case strings.HasPrefix(expr, "@every "):
		return parseIntervalExpr(expr)
	default:
		return parseCronExpr(expr)
	}
}

// 解析一次性任务
func parseOnceExpr(expr string) (*taskItem, error) {
	layout := "2006-01-02 15:04:05.999"
	str := strings.TrimPrefix(expr, "@once ")
	t, err := time.Parse(layout, str)
	if err != nil {
		return nil, fmt.Errorf("invalid once format: %v", err)
	}
	return &taskItem{
		exprType: exprOnce,
		next:     t,
	}, nil
}

// 解析间隔任务
func parseIntervalExpr(expr string) (*taskItem, error) {
	durationStr := strings.TrimPrefix(expr, "@every ")
	duration, err := time.ParseDuration(durationStr)
	if err != nil {
		return nil, fmt.Errorf("invalid interval format: %v", err)
	}
	return &taskItem{
		exprType: exprInterval,
		next:     time.Now().Add(duration),
		interval: duration,
	}, nil
}

func parseCronExpr(expr string) (*taskItem, error) {
	parts := strings.Fields(expr)
	if len(parts) != 7 { // 包含毫秒字段
		return nil, errors.New("invalid cron format: [millis] [sec] [min] [hour] [dom] [month] [dow]")
	}

	// 解析毫秒（必须为第一个字段）
	millis, err := strconv.Atoi(parts[0])
	if err != nil || millis < 0 || millis > 999 {
		return nil, errors.New("invalid milliseconds (0-999)")
	}

	// 初始化调度器配置
	cronSchedule := &cronSchedule{
		millis: millis,
		sec:    parseCronField(parts[1], 0, 59),             // 秒
		min:    parseCronField(parts[2], 0, 59),             // 分
		hour:   parseCronField(parts[3], 0, 23),             // 时
		dom:    parseCronField(parts[4], 1, 31),             // 日
		month:  time.Month(parseCronField(parts[5], 1, 12)), // 月
		dow:    parseCronField(parts[6], 0, 6),              // 周
	}

	return &taskItem{
		exprType: exprCron,
		schedule: cronSchedule,
		next:     cronSchedule.Next(time.Now()),
	}, nil
}

// 通用字段解析器
func parseCronField(field string, min, max int) int {
	if field == "*" {
		return -1 // 通配符标识
	}

	val, err := strconv.Atoi(field)
	if err != nil || val < min || val > max {
		return -2 // 错误标识
	}
	return val
}
